package com.maxlen.goods.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maxlen.common.constant.ProductConstant;
import com.maxlen.common.to.SkuReductionTO;
import com.maxlen.common.to.SpuBoundTO;
import com.maxlen.common.to.es.SkuEsModel;
import com.maxlen.common.utils.*;
import com.maxlen.goods.dao.SpuInfoDao;
import com.maxlen.goods.entity.*;
import com.maxlen.goods.entity.dto.ProductAttrValueDTO;
import com.maxlen.goods.entity.dto.SkuItemDTO;
import com.maxlen.goods.entity.vo.SkuHasStockVO;
import com.maxlen.goods.entity.vo.SpuInfoByIdAndNameVO;
import com.maxlen.goods.entity.vo.SpuInfoPageParamsVO;
import com.maxlen.goods.entity.vo.spuAdd.*;
import com.maxlen.goods.feign.CouponFeignService;
import com.maxlen.goods.feign.SearchFeignService;
import com.maxlen.goods.feign.WareFeignService;
import com.maxlen.goods.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    private SpuInfoDescService spuInfoDescService;

    @Autowired
    private SpuImagesService spuImagesService;

    @Autowired
    private ProductAttrValueService productAttrValueService;

    @Autowired
    private SkuInfoService skuInfoService;

    @Autowired
    private SkuImagesService skuImagesService;

    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    private CouponFeignService couponFeignService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private AttrService attrService;

    @Autowired
    private WareFeignService wareFeignService;

    @Autowired
    private SearchFeignService searchFeignService;

    @Override
    public PageUtils queryPage(SpuInfoPageParamsVO params) {
        LambdaQueryWrapper<SpuInfoEntity> wrapper = new LambdaQueryWrapper<>();

        String key = params.getKey();
        if(StringUtils.hasText(key)){
            wrapper.like(SpuInfoEntity::getSpuName, key);
        }

        String status = params.getStatus();
        if(StringUtils.hasText(status)){
            wrapper.eq(SpuInfoEntity::getPublishStatus, status);
        }

        String brandId = params.getBrandId();
        if(StringUtils.hasText(brandId) && !"0".equals(brandId)){
            wrapper.eq(SpuInfoEntity::getBrandId, brandId);
        }

        String catelogId = params.getCatelogId();
        if(StringUtils.hasText(catelogId) && !"0".equals(catelogId)){
            wrapper.eq(SpuInfoEntity::getCatalogId, catelogId);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Page<>(params.getPage(), params.getLimit()),
                wrapper
        );

        return new PageUtils(page);
    }

    /**
     * 发布商品所有信息
     * //TODO 高级部分
     * @param vo
     */
    @Override
    @Transactional
    public void saveAllDetail(SpuSaveVO vo) {

        // 保存 spu 基本信息 pms_spu_info
        SpuInfoEntity spuInfoEntity = CopyUtils.copy(vo, SpuInfoEntity.class);
        this.saveDetail(spuInfoEntity);

        Long spuId = spuInfoEntity.getId();

        // 保存 spu 的描述 pms_spu_info_desc
        List<String> decript = vo.getDecript();
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setSpuId(spuId);
        spuInfoDescEntity.setDecript(String.join(",", decript));
        spuInfoDescService.saveDetail(spuInfoDescEntity);

        // 保存 spu 的图片 pms_spu_images
        List<String> images = vo.getImages();
        spuImagesService.saveDetail(spuId, images);

        // 保存 spu 的规格参数 pms_product_attr_value
        List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
        if(baseAttrs!=null && !baseAttrs.isEmpty()){
            List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream().map(item -> {
                ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
                productAttrValueEntity.setSpuId(spuId);
                productAttrValueEntity.setAttrId(item.getAttrId());
                productAttrValueEntity.setAttrName(item.getAttrName());
                productAttrValueEntity.setAttrValue(item.getAttrValues());
                productAttrValueEntity.setQuickShow(item.getShowDesc());
                return productAttrValueEntity;
            }).collect(Collectors.toList());
            productAttrValueService.saveDetailList(productAttrValueEntities);
        }


        // 保存 spu 积分信息 maxlen-sms -> sms_spu_bounds
        Bounds bounds = vo.getBounds();
        SpuBoundTO spuBoundTO = CopyUtils.copy(bounds, SpuBoundTO.class);
        spuBoundTO.setSpuId(spuId);
        R r1 = couponFeignService.saveSpuBound(spuBoundTO);
        if(r1.getCode() != 0){
            log.error("远程保存 spu 积分信息失败");
        }

        // 保存 sku 基本信息 pms_sku_info
        List<Skus> skus = vo.getSkus();
        if(skus!=null && skus.isEmpty()){
            return;
        }
        skus.forEach(item -> {
            List<Images> imagesList = item.getImages();

            String defaultImg = null;
            if(imagesList != null && !imagesList.isEmpty()){
                for (Images img : imagesList) {
                    if(img.getDefaultImg() == 1){
                        defaultImg = img.getImgUrl();
                    }
                }
            }
            SkuInfoEntity skuInfoEntity = CopyUtils.copy(item, SkuInfoEntity.class);
            skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
            skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
            skuInfoEntity.setSpuId(spuId);
            skuInfoEntity.setSaleCount(0L);
            skuInfoEntity.setSkuDefaultImg(defaultImg);
            skuInfoService.saveDetail(skuInfoEntity);
            Long skuId = skuInfoEntity.getSkuId();

            // 保存 sku 图片 pms_sku_images
            if(imagesList != null && !imagesList.isEmpty()) {
                List<SkuImagesEntity> skuImagesEntityList = imagesList.stream()
                        .filter(images1 -> {
                            String imgUrl = images1.getImgUrl();
                            if (imgUrl != null && imgUrl.length() != 0) {
                                return true;
                            }
                            return false;
                        })
                        .map(img -> {
                            SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                            skuImagesEntity.setSkuId(skuId);
                            skuImagesEntity.setImgUrl(img.getImgUrl());
                            skuImagesEntity.setDefaultImg(img.getDefaultImg());
                            return skuImagesEntity;
                        }).collect(Collectors.toList());
                skuImagesService.saveDetailAll(skuImagesEntityList);
            }

            // 保存 sku 销售属性信息 pms_sku_sale_attr_value
            List<Attr> attrList = item.getAttr();
            List<SkuSaleAttrValueEntity> skuSaleAttrValueEntityList = attrList.stream().map(attr -> {
                SkuSaleAttrValueEntity skuSaleAttrValueEntity = CopyUtils.copy(attr, SkuSaleAttrValueEntity.class);
                skuSaleAttrValueEntity.setSkuId(skuId);
                return skuSaleAttrValueEntity;
            }).collect(Collectors.toList());
            skuSaleAttrValueService.saveDetailAll(skuSaleAttrValueEntityList);

            // 保存 sku 的优惠、满减等信息 maxlen-sms -> sms_sku_ladder \ sms_sku_full_reduction \ sms_member_price
            SkuReductionTO skuReductionTO = CopyUtils.copy(item, SkuReductionTO.class);
            skuReductionTO.setSkuId(skuId);
            R r = couponFeignService.saveSkuReduction(skuReductionTO);
            if(r.getCode() != 0){
                log.error("远程保存 sku 优惠信息失败");
            }
        });
    }

    @Override
    public void saveDetail(SpuInfoEntity spuInfoEntity) {
        baseMapper.insert(spuInfoEntity);
    }

    @Override
    public R updateByPublishStatus(Long spuId) {
        List<SkuInfoEntity> skuInfoEntityList = skuInfoService.getSkusBySpuId(spuId);
        if(skuInfoEntityList.isEmpty()){
            return R.error("商品不存在");
        }

        SkuInfoEntity skuInfoEntity = skuInfoEntityList.get(0);
        // 查询品牌信息
        BrandEntity brandEntity = brandService.getById(skuInfoEntity.getBrandId());
        // 查询分类信息
        CategoryEntity categoryEntity = categoryService.getById(skuInfoEntity.getCatalogId());

        // 查询 sku 所有可以被用来检索的规格属性
        List<ProductAttrValueEntity> productAttrValueEntityList = productAttrValueService.baseAttrListForSpu(spuId);
        List<SkuEsModel.Attrs> attrsList = new ArrayList<>();
        if(!productAttrValueEntityList.isEmpty()){
            List<Long> attrIdList = productAttrValueEntityList.stream()
                    .map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());

            List<Long> attr = attrService.getAttrByIdAndSearchType(attrIdList);
            Set<Long> idSet = new HashSet<>(attr);
            attrsList = productAttrValueEntityList.stream()
                    .filter(productAttrValueEntity -> {
                        return idSet.contains(productAttrValueEntity.getAttrId());
                    })
                    .map(productAttrValueEntity -> {
                        return CopyUtils.copy(productAttrValueEntity, SkuEsModel.Attrs.class);

                    }).collect(Collectors.toList());
        }

        // 发送远程调用，库存系统查询是否有库存
        Map<Long, Long> stockMap = null;
        List<Long> skuIdList = skuInfoEntityList.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        try{
            R r = wareFeignService.getSkuHasStock(skuIdList);
            if(r.isOk()){
                List<SkuHasStockVO> skuHasStockVOList = r.getData(new TypeReference<List<SkuHasStockVO>>() {});
                stockMap = skuHasStockVOList.stream().collect(Collectors.toMap(SkuHasStockVO::getSkuId, SkuHasStockVO::getHasStock));
            }
        }catch (Exception e){
            log.error("库存系统错误，原因{}",e);
            return R.error("库存系统异常，请联系管理员");
        }

        List<SkuEsModel.Attrs> finalAttrsList = attrsList;
        Map<Long, Long> finalStockMap = stockMap;
        List<SkuEsModel> skuEsModelList = skuInfoEntityList.stream().map(skuInfo -> {

            SkuEsModel skuEsModel = CopyUtils.copy(skuInfo, SkuEsModel.class);
            skuEsModel.setSkuPrice(skuInfo.getPrice());
            skuEsModel.setSkuImg(skuInfo.getSkuDefaultImg());

            skuEsModel.setBrandName(brandEntity.getName());
            skuEsModel.setBrandImg(brandEntity.getLogo());

            skuEsModel.setCatalogName(categoryEntity.getName());

            // 设置检索属性
            skuEsModel.setAttrs(finalAttrsList);

            // 设置热度评分
            skuEsModel.setHotScore(0L);

            // 设置是否有库存
            if(finalStockMap == null){
                skuEsModel.setHasStock(true);
            }else{
                Long aLong = finalStockMap.get(skuInfo.getSkuId());
                if(aLong != null){
                    skuEsModel.setHasStock(aLong > 0);
                }else{
                    skuEsModel.setHasStock(false);
                }
            }

            return skuEsModel;
        }).collect(Collectors.toList());

        // 发送给 es 进行保存
        R r = null;
        try {
            r = searchFeignService.productStatusUp(skuEsModelList);
        } catch (Exception e) {
            log.error("检索系统错误，原因{}",e);
            return R.error("检索系统异常，请联系管理员");
        }
        if(r != null && r.isOk()){
            SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
            spuInfoEntity.setId(spuId);
            spuInfoEntity.setPublishStatus(ProductConstant.StatusEnum.SPU_UP.getCode());

            baseMapper.updateById(spuInfoEntity);
        }else{
            //TODO 重复调用？接口幂等性，重试机制
            /**
             * 构造请求数据，将对象转为 json
             *      RequestTemplate template = buildTemplateFromArgs.create(argv)
             * 发送请求进行执行（执行成功会解码响应数据）
             *      executeAndDecode（template）
             * 执行请求会有重试机制
             *      while(true){
             *          try{
             *              executeAndDecode（template）
             *          }catch(){
             *              try{
             *                  retryer.continueOrPropagate(e);
             *              }catch{
             *                  throw ex;
             *              }
             *              continue;
             *          }
             *      }
             */
        }

        return R.ok();
    }

    @Override
    public BigDecimal getWeightById(Long spuId) {
        LambdaQueryWrapper<SpuInfoEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SpuInfoEntity::getId, spuId);
        wrapper.select(SpuInfoEntity::getWeight);
        SpuInfoEntity spuInfoEntity = baseMapper.selectOne(wrapper);
        return spuInfoEntity.getWeight();
    }

    @Override
    public BigDecimal getWeightBySkuId(Long skuId) {
        SkuInfoEntity byId = skuInfoService.getById(skuId);
        return this.getWeightById(byId.getSpuId());
    }

    @Override
    public R getSpuAll() {
        List<SpuInfoEntity> spuInfoEntityList = baseMapper.selectList(new LambdaQueryWrapper<SpuInfoEntity>()
                .select(SpuInfoEntity::getId, SpuInfoEntity::getSpuName)
                .eq(SpuInfoEntity::getPublishStatus, ProductConstant.StatusEnum.SPU_UP.getCode()));
        List<SpuInfoByIdAndNameVO> spuInfoByIdAndNameVOList = CopyUtils.copyList(spuInfoEntityList, SpuInfoByIdAndNameVO.class);
        return R.ok().setData(spuInfoByIdAndNameVOList);
    }

    @Override
    public List<Long> getIdsByCategoryIds(List<Long> categoryIds) {
        List<SpuInfoEntity> spuInfoEntityList = baseMapper.selectList(new LambdaQueryWrapper<SpuInfoEntity>()
                .select(SpuInfoEntity::getId)
                .in(SpuInfoEntity::getCatalogId, categoryIds));
        return spuInfoEntityList.stream().map(SpuInfoEntity::getId).collect(Collectors.toList());
    }

}
